﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SD007
{
    public abstract class ErrorType
    {
        private string description;

        public string Description
        {
            get { return description; }
            set { description = value; }
        }

        private string typeName;

        public string TypeName
        {
            get { return typeName; }
            set { typeName = value; }
        }

        private int line;

        public int Line
        {
            get { return line; }
            set { line = value; }
        }

        private int column;

        public int Column
        {
            get { return column; }
            set { column = value; }
        }

        private string file;

        public string File
        {
            get { return file; }
            set { file = value; }
        }

        public ErrorType(int line, int column, string file)
        {
            this.Line = line;
            this.Column = column;
            this.File = file;
            this.Initialize();
        }

        public abstract void Initialize();

        private List<Tuple<Metric, string>> metrics;

        public virtual List<Tuple<Metric, string>> Metrics
        {
            get { return metrics; }
            set { metrics = value; }
        }
    }

    public class GodClassErrorType : ErrorType
    {
        public GodClassErrorType(int line, int column, string file)
            : base(line, column, file)
        {
        }

        public override void Initialize()
        {
            this.Description = @"Uma God Class é uma classe que tende a centralizar a inteligência do sistema. Uma classe deus realiza muito trabalho sozinha, delegando apenas pequenos detalhes a um conjunto de classes triviais e usando dados de outras classes”. Classes deus tendem a possuir um baixo nível de coesão, isto é, os seus métodos constituintes possuem interesses distintos. Além disso, esse tipo de classe costuma possuir alta complexidade ciclomática distribuída pelos seus métodos.";
            this.TypeName = "God class";
        }

        private ATFD atfd = new ATFD();
        private TCC tcc = new TCC();
        private WMC wmc = new WMC();

        private int aTFDVal;

        public int ATFDVal
        {
            get { return aTFDVal; }
            set { aTFDVal = value; }
        }

        private Decimal tCCVal;

        public Decimal TCCVal
        {
            get { return tCCVal; }
            set { tCCVal = value; }
        }

        private int wMCVal;

        public int WMCVal
        {
            get { return wMCVal; }
            set { wMCVal = value; }
        }

        public override List<Tuple<Metric, string>> Metrics
        {
            get
            {
                return new List<Tuple<Metric, string>>()
                {
                    new Tuple<Metric, string>( this.atfd, this.ATFDVal.ToString() ),
                    new Tuple<Metric, string>( this.tcc, this.TCCVal.ToString() ),
                    new Tuple<Metric, string>( this.wmc, this.WMCVal.ToString() )
                };
            }
            set
            {
                base.Metrics = value;
            }
        }
    }

    public class DataClassErrorType : ErrorType
    {
        public DataClassErrorType(int line, int column, string file)
            : base(line, column, file)
        {
        }

        public override void Initialize()
        {
            this.Description = @"Esse tipo de classe, em geral, possui pouco comportamento e muitos dados expostos através de métodos de acesso ou atributos públicos. O comportamento dessas classes tende a ser implementado por outras classes.";
            this.TypeName = "Data class";
        }

        private NOPA nopa = new NOPA();
        private NOAM noam = new NOAM();
        private WOC woc = new WOC();
        private WMC wmc = new WMC();

        private int nOPAVal;

        public int NOPAVal
        {
            get { return nOPAVal; }
            set { nOPAVal = value; }
        }

        private int nOAMVal;

        public int NOAMVal
        {
            get { return nOAMVal; }
            set { nOAMVal = value; }
        }

        private Decimal wOCVal;

        public Decimal WOCVal
        {
            get { return wOCVal; }
            set { wOCVal = value; }
        }

        private int wMCVal;

        public int WMCVal
        {
            get { return wMCVal; }
            set { wMCVal = value; }
        }

        public override List<Tuple<Metric, string>> Metrics
        {
            get
            {
                return new List<Tuple<Metric, string>>()
                {
                    new Tuple<Metric, string>( this.nopa, this.NOPAVal.ToString() ),
                    new Tuple<Metric, string>( this.noam, this.NOAMVal.ToString() ),
                    new Tuple<Metric, string>( this.wmc, this.WMCVal.ToString() ),
                    new Tuple<Metric, string>( this.woc, this.WOCVal.ToString() )
                };
            }
            set
            {
                base.Metrics = value;
            }
        }

    }

    public class LargeClassErrorType : ErrorType
    {
        public LargeClassErrorType(int line, int column, string file)
            : base(line, column, file)
        {
        }

        private WMC wmc = new WMC();

        private int wMCVal;

        public int WMCVal
        {
            get { return wMCVal; }
            set { wMCVal = value; }
        }

        public override void Initialize()
        {
            this.Description = @"Ocorre em classes que possuem muitas funcionalidades. Em geral, esse tipo de classe possui muitas variáveis de instância.";
            this.TypeName = "Large class";
        }

        public override List<Tuple<Metric, string>> Metrics
        {
            get
            {
                return new List<Tuple<Metric, string>>()
                {
                    new Tuple<Metric, string>((Metric) this.wmc, this.WMCVal.ToString())
                };
            }
            set
            {
                base.Metrics = value;
            }
        }
    }

    public class BrainMethodErrorType : ErrorType
    {
        public BrainMethodErrorType(int line, int column, string file)
            : base(line, column, file)
        {
        }

        public override void Initialize()
        {
            this.Description = @"É um método de difícil compreensão e manutenção dado o seu grande tamanho. Esse tipo de método tende a centralizar as funcionalidades de uma classe.";
            this.TypeName = "Brain method";
        }

        private LOC loc = new LOC();

        private int lOCVal;

        public int LOCVal
        {
            get { return lOCVal; }
            set { lOCVal = value; }
        }

        private CYCLO cyclo = new CYCLO();

        private int cYCLOVal;

        public int CYCLOVal
        {
            get { return cYCLOVal; }
            set { cYCLOVal = value; }
        }

        private MAXNESTING maxnesting = new MAXNESTING();

        private int mAXNESTINGVal;

        public int MAXNESTINGVal
        {
            get { return mAXNESTINGVal; }
            set { mAXNESTINGVal = value; }
        }

        private NOAV noav = new NOAV();

        private int nOAVVal;

        public int NOAVVal
        {
            get { return nOAVVal; }
            set { nOAVVal = value; }
        }

        public override List<Tuple<Metric, string>> Metrics
        {
            get
            {
                return new List<Tuple<Metric, string>>()
                {
                    new Tuple<Metric, string>((Metric) this.loc, this.LOCVal.ToString()),
                    new Tuple<Metric, string>((Metric) this.cyclo, this.CYCLOVal.ToString()),
                    new Tuple<Metric, string>((Metric) this.maxnesting, this.MAXNESTINGVal.ToString()),
                    new Tuple<Metric, string>((Metric) this.noav, this.NOAVVal.ToString())
                };
            }
            set
            {
                base.Metrics = value;
            }
        }
    }

    public class LongParameterListErrorType : ErrorType
    {
        public LongParameterListErrorType(int line, int column, string file)
            : base(line, column, file)
        {
        }

        public override void Initialize()
        {
            this.Description = @"É uma lista de parâmetros que torna difícil a chamada do seu método subjacente, dado o seu grande tamanho.";
            this.TypeName = "Long parameter list";
        }

        private NOP nop = new NOP();

        private int nOPVal;

        public int NOPVal
        {
            get { return nOPVal; }
            set { nOPVal = value; }
        }

        public override List<Tuple<Metric, string>> Metrics
        {
            get
            {
                return new List<Tuple<Metric, string>>()
                {
                    new Tuple<Metric, string>((Metric) this.nop, this.nOPVal.ToString())
                };
            }
            set
            {
                base.Metrics = value;
            }
        }
    }

    public class Metric
    {
        private string name;

        public virtual string Name
        {
            get { return name; }
            set { name = value; }
        }

        private string description;

        public virtual string Description
        {
            get { return description; }
            set { description = value; }
        }
    }

    public class WMC : Metric
    {
        public override string Name
        {
            get
            {
                return "WMC";
            }
        }

        public override string Description
        {
            get
            {
                return @"A soma da complexidade estática de todos os métodos de uma classe. O complexidade ciclomática é usada para quantificar a complexidade dos métodos.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class NOPA : Metric
    {
        public override string Name
        {
            get
            {
                return "NOPA";
            }
        }

        public override string Description
        {
            get
            {
                return @"O número de atributos públicos de uma classe.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class NOAM : Metric
    {
        public override string Name
        {
            get
            {
                return "NOAM";
            }
        }

        public override string Description
        {
            get
            {
                return @"O número de métodos de acesso (getters e setters) de uma classe.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class WOC : Metric
    {
        public override string Name
        {
            get
            {
                return "WOC";
            }
        }

        public override string Description
        {
            get
            {
                return @"É o número de métodos públicos “funcionais” dividido pelo número total de membros públicos.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class NOP : Metric
    {
        public override string Name
        {
            get
            {
                return "NOP";
            }
        }

        public override string Description
        {
            get
            {
                return @"Número de parâmetros de um método.";
            }
            set
            {
                base.Description = value;
            }
        }        
    }

    public class TCC : Metric
    {
        public override string Name
        {
            get
            {
                return "TCC";
            }
        }

        public override string Description
        {
            get
            {
                return @"O número relativo aos pares de métodos de uma classe que acessam pelo menos um atributo da classe medida em comum.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class ATFD : Metric
    {
        public override string Name
        {
            get
            {
                return "ATFD";
            }
        }

        public override string Description
        {
            get
            {
                return @"O número de atributos de classes não relacionadas que são acessados diretamente ou invocando métodos de acesso.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class LOC : Metric
    {
        public override string Name
        {
            get
            {
                return "LOC";
            }
        }

        public override string Description
        {
            get
            {
                return "Conta o número de linhas de código de uma operação, incluindo linhas em branco e comentários.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class CYCLO : Metric
    {
        public override string Name
        {
            get
            {
                return "CYCLO";
            }
        }

        public override string Description
        {
            get
            {
                return "O número de caminhos linearmente independentes do início ao fim de uma operação.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class MAXNESTING : Metric
    {
        public override string Name
        {
            get
            {
                return "MAXNESTING";
            }
        }

        public override string Description
        {
            get
            {
                return "O nível máximo de aninhamento de estruturas de controle dentro de uma operação.";
            }
            set
            {
                base.Description = value;
            }
        }
    }

    public class NOAV : Metric
    {
        public override string Name
        {
            get
            {
                return "NOAV";
            }
        }

        public override string Description
        {
            get
            {
                return "O número total de variáveis acessadas diretamente de uma operação medida. Variáveis incluem parâmetros, variáveis locais, mas também variáveis de instância e variáveis globais.";
            }
            set
            {
                base.Description = value;
            }
        }
    }
}
